package com.flyduck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyduck.entity.SysRole;
import com.flyduck.entity.SysRoleMenu;
import com.flyduck.entity.SysUserRole;
import com.flyduck.manager.SysPermissionCacheManager;
import com.flyduck.mapper.SysRoleMapper;
import com.flyduck.mapper.SysRoleMenuMapper;
import com.flyduck.mapper.SysUserRoleMapper;
import com.flyduck.service.SysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flyduck.utils.BeanUtils;
import com.flyduck.utils.PageUtils;
import com.flyduck.utils.StringUtils;
import com.flyduck.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author flyduck
 * @since 2024-05-27
 */
@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Autowired
    private SysPermissionCacheManager sysPermissionCacheManager;

    @Override
    public SysRoleDetailsRespVO getRoleDetailsById(Long id) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        SysRoleDetailsRespVO sysRoleDetailsRespVO = BeanUtils.toBean(sysRole, SysRoleDetailsRespVO.class);

        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectList(
                new LambdaQueryWrapper<SysRoleMenu>()
                        .eq(SysRoleMenu::getRoleId, id)
        );
        List<Long> menuIds = sysRoleMenuList.stream()
                .map(SysRoleMenu::getMenuId)
                .collect(Collectors.toList());
        sysRoleDetailsRespVO.setMenuIds(menuIds);

        return sysRoleDetailsRespVO;
    }

    @Override
    public Page<SysRoleRespVO> getRolePageBySysRoleQueryReqVO(Page page, SysRoleQueryReqVO sysRoleQueryReqVO) {
        Page<SysRole> sysRolePage = sysRoleMapper.selectPage(page,
                new LambdaQueryWrapper<SysRole>()
                        .like(StringUtils.isNotBlank(sysRoleQueryReqVO.getName()), SysRole::getName, sysRoleQueryReqVO.getName())
        );

        return PageUtils.convert(sysRolePage, SysRoleRespVO.class);
    }

    @Override
    public void saveRole(SysRoleSaveReqVO sysRoleSaveReqVO) {
        SysRole sysRole = BeanUtils.toBean(sysRoleSaveReqVO, SysRole.class);
        sysRole.setCreated(LocalDateTime.now());
        sysRoleMapper.insert(sysRole);
    }

    @Override
    public void updateRole(SysRoleUpdateReqVO sysRoleUpdateReqVO) {
        SysRole sysRole = BeanUtils.toBean(sysRoleUpdateReqVO, SysRole.class);
        sysRole.setUpdated(LocalDateTime.now());
        sysRoleMapper.updateById(sysRole);

        //删除角色关联用户的所有权限
        sysPermissionCacheManager.clearPermissionListByRoleId(sysRoleUpdateReqVO.getId());
    }

    @Transactional
    @Override
    public void deleteByIds(List<Long> ids) {
        sysRoleMapper.deleteBatchIds(ids);

        //删除角色关联表
        sysUserRoleMapper.delete(
                new LambdaQueryWrapper<SysUserRole>()
                .in(SysUserRole::getRoleId,ids)

        );
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>()
                .in(SysRoleMenu::getRoleId,ids)
        );

        //删除角色关联用户的所有权限
        ids.stream().forEach(id -> {
            sysPermissionCacheManager.clearPermissionListByRoleId(id);
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void assignMenuListToRole(Long roleId, List<Long> menuIds) {
        //先删除之前的
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId,roleId)
        );

        //保存新的关系
        List<SysRoleMenu> sysRoleMenuList = menuIds.stream()
                .map(menuId -> {
                    SysRoleMenu sysRoleMenu = new SysRoleMenu();
                    sysRoleMenu.setRoleId(roleId);
                    sysRoleMenu.setMenuId(menuId);
                    return sysRoleMenu;
                }).collect(Collectors.toList());
        sysRoleMenuMapper.insertBatch(sysRoleMenuList);

        //删除相关的缓存信息
        sysPermissionCacheManager.clearPermissionListByRoleId(roleId);
    }
}
